
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <functional>
#include <thread>
#include <iostream>
#include <Windows.h>
#include <chrono>
#include <string>
#include <sstream>
#include <iosfwd>
#include <iomanip>

using namespace std;

constexpr int64_t SEC = 1000000;
constexpr int64_t MIN = SEC * 60;
constexpr int64_t HOUR = MIN * 60;
constexpr int64_t DAY = HOUR * 24;

// 返回当前时间作为 格林威治(GMT)时间 距离 GMT时间 1970-1-1 00:00:00 的微秒数

int64_t get_time(){
    chrono::system_clock clock;
    return chrono::duration_cast<chrono::microseconds>(
        clock.now().time_since_epoch()).count();
}

int64_t get_time_us_greenwich()   
{
    chrono::system_clock clock;
    return chrono::duration_cast<chrono::microseconds>(
        clock.now().time_since_epoch()).count();
}

// 返回当前时间作为 本地（北京）时间 距离 GMT时间 1970-1-1 00:00:00 的微秒数，等于get_gmtime_us加8小时
int64_t get_localtime_us()
{
    return get_time_us_greenwich() + HOUR * 8;
}

// 格林威治时间的微秒数格式化成本地时间字符串
string gmtime2localstr(int64_t time_us, const string& fmt="%Y-%m-%d %H:%M:%S")
{
    stringstream ss;
    time_t t = time_us / SEC;
    auto tm = std::localtime(&t);
    ss << std::put_time(tm, fmt.c_str());
    return ss.str();
}

// 本地时间字符串解析成格林威治时间的微秒数
int64_t localstr2gmtime(const std::string& s, const std::string& fmt="%Y-%m-%d %H:%M:%S")
{
    stringstream ss;
    ss << s;
    struct tm tm;
    ss >> std::get_time(&tm, fmt.c_str());
    return (int64_t)mktime(&tm) * SEC;
}

// 字符串转微秒数，不考虑时区
std::string time2strgm(int64_t time_us, const std::string& fmt="%Y-%m-%d %H:%M:%S")
{
    stringstream ss;
    time_t t = time_us / SEC;
    auto tm = std::gmtime(&t);
    ss << std::put_time(tm, fmt.c_str());
    return ss.str();
}

std::string time2strlocal(int64_t time_us,const std::string &fmt="%Y-%m-%d %H:%M:%S"){
	stringstream ss;
    time_t t = time_us / SEC;
    auto tm = std::localtime(&t);
    ss << std::put_time(tm, fmt.c_str());
    return ss.str();
}


// 微秒数转字符串，不考虑时区
int64_t str2time(const std::string& s, const std::string& fmt="%Y-%m-%d %H:%M:%S")
{
    stringstream ss;
    ss << s;
    struct tm tm;
    ss >> std::get_time(&tm, fmt.c_str());
    return (int64_t)mktime(&tm) * SEC + HOUR * 8; // 这里 + 8 HOURs是因为mktime内部考虑了时区，我期望有一个gmmktime函数，但是标准库似乎并没有
}

void time_add(){
	using std::chrono::system_clock;
	std::chrono::duration<int,std::ratio<60*60*24> > one_day (1);
	system_clock::time_point today = system_clock::now();
	system_clock::time_point tomorrow = today + one_day;
	std::time_t tt;

	tt = system_clock::to_time_t ( today );
	std::cout << "today is: " << ctime(&tt);

	tt = system_clock::to_time_t ( tomorrow );
	std::cout << "tomorrow will be: " << ctime(&tt);
}

std::string stdtime(){
    return time2strgm(get_time_us_greenwich());
}